<script setup>
import { every, get, includes, isEmpty, map, reject, sortBy, toNumber, trim } from 'lodash'
import { computed, nextTick, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { ListSentinelMasters, TestConnection } from 'wailsjs/go/services/connectionService.js'
import useDialog, { ConnDialogType } from 'stores/dialog'
import Close from '@/components/icons/Close.vue'
import useConnectionStore from 'stores/connections.js'
import FileOpenInput from '@/components/common/FileOpenInput.vue'
import { KeyViewType } from '@/consts/key_view_type.js'
import { useThemeVars } from 'naive-ui'
import useBrowserStore from 'stores/browser.js'
import Delete from '@/components/icons/Delete.vue'
import Add from '@/components/icons/Add.vue'
import IconButton from '@/components/common/IconButton.vue'

/**
 * Dialog for new or edit connection
 */

const themeVars = useThemeVars()
const dialogStore = useDialog()
const connectionStore = useConnectionStore()
const browserStore = useBrowserStore()
const i18n = useI18n()

const editName = ref('')
const generalForm = ref(null)
const generalFormRules = () => {
    const requiredMsg = i18n.t('dialogue.field_required')
    const illegalChars = ['/', '\\']
    return {
        name: [
            { required: true, message: requiredMsg, trigger: 'input' },
            {
                validator: (rule, value) => {
                    return every(illegalChars, (c) => !includes(value, c))
                },
                message: i18n.t('dialogue.illegal_characters'),
                trigger: 'input',
            },
        ],
        addr: { required: true, message: requiredMsg, trigger: 'input' },
        defaultFilter: { required: true, message: requiredMsg, trigger: 'input' },
        keySeparator: { required: true, message: requiredMsg, trigger: 'input' },
    }
}
const isEditMode = computed(() => dialogStore.connType === ConnDialogType.EDIT)
const closingConnection = computed(() => {
    if (isEmpty(editName.value)) {
        return false
    }
    return browserStore.isConnected(editName.value)
})

const groupOptions = computed(() => {
    const options = map(connectionStore.groups, (group) => ({
        label: group,
        value: group,
    }))
    options.splice(0, 0, {
        label: 'dialogue.connection.no_group',
        value: '',
    })
    return options
})

const dbFilterList = ref([])
const onUpdateDBFilterType = (t) => {
    if (t !== 'none') {
        // set default filter index if empty
        if (isEmpty(dbFilterList.value)) {
            dbFilterList.value = ['0']
        }
    }
}

const aliasPair = ref([
    /*{ db: 0, alias: '' }*/
])
const onCreateAlias = () => {
    return {
        db: 0,
        alias: '',
    }
}
const onUpdateAlias = () => {
    const val = reject(aliasPair.value, (v) => v == null || isEmpty(v.alias))
    const result = {}
    for (const elem of val) {
        result[elem.db] = elem.alias
    }
    generalForm.value.alias = result
}

watch(
    () => dbFilterList.value,
    (list) => {
        const dbList = map(list, (item) => {
            const idx = toNumber(item)
            return isNaN(idx) ? 0 : idx
        })
        generalForm.value.dbFilterList = sortBy(dbList)
    },
    { deep: true },
)

const sshLoginType = computed(() => {
    return get(generalForm.value, 'ssh.loginType', 'pwd')
})

const loadingSentinelMaster = ref(false)
const masterNameOptions = ref([])
const onLoadSentinelMasters = async () => {
    try {
        loadingSentinelMaster.value = true
        const { success, data, msg } = await ListSentinelMasters(generalForm.value)
        if (!success || isEmpty(data)) {
            $message.error(msg || 'list sentinel master fail')
        } else {
            const options = []
            for (const m of data) {
                options.push({
                    label: m['name'],
                    value: m['name'],
                })
            }

            // select default names
            if (!isEmpty(options)) {
                generalForm.value.sentinel.master = options[0].value
            }
            masterNameOptions.value = options
        }
    } catch (e) {
        $message.error(e.message)
    } finally {
        loadingSentinelMaster.value = false
    }
}

const tab = ref('general')
const testing = ref(false)
const testResult = ref(null)
const showTestResult = computed(() => {
    return !testing.value && testResult.value != null
})
const predefineColors = ref(['', '#F75B52', '#F7A234', '#F7CE33', '#4ECF60', '#348CF7', '#B270D3'])
const generalFormRef = ref(null)
const advanceFormRef = ref(null)

const onSaveConnection = async () => {
    // validate general form
    await generalFormRef.value?.validate((err) => {
        if (err) {
            nextTick(() => (tab.value = 'general'))
        }
    })

    // validate advance form
    await advanceFormRef.value?.validate((err) => {
        if (err) {
            nextTick(() => (tab.value = 'advanced'))
        }
    })

    // trim addr by network type
    if (get(generalForm.value, 'network', 'tcp') === 'unix') {
        generalForm.value.network = 'unix'
        generalForm.value.addr = ''
        generalForm.value.port = 0
        generalForm.value.sock = trim(generalForm.value.sock)
    } else {
        generalForm.value.network = 'tcp'
        generalForm.value.sock = ''
        generalForm.value.addr = trim(generalForm.value.addr)
    }

    // trim advance data
    if (get(generalForm.value, 'dbFilterType', 'none') === 'none') {
        generalForm.value.dbFilterList = []
    }

    // trim ssl data
    if (!!!generalForm.value.ssl.enable) {
        generalForm.value.ssl = {}
    }

    // trim ssh login data
    if (!!generalForm.value.ssh.enable) {
        switch (generalForm.value.ssh.loginType) {
            case 'pkfile':
                generalForm.value.ssh.password = ''
                break
            default:
                generalForm.value.ssh.pkFile = ''
                generalForm.value.ssh.passphrase = ''
                break
        }
    } else {
        // ssh disabled, reset to default value
        generalForm.value.ssh = {}
    }

    // trim sentinel data
    if (!!!generalForm.value.sentinel.enable) {
        generalForm.value.sentinel = {}
    }

    // trim cluster data
    if (!!!generalForm.value.cluster.enable) {
        generalForm.value.cluster = {}
    }

    // trim proxy data
    if (generalForm.value.proxy.type !== 2) {
        generalForm.value.proxy.schema = ''
        generalForm.value.proxy.addr = ''
        generalForm.value.proxy.port = 0
        generalForm.value.proxy.auth = false
        generalForm.value.proxy.username = ''
        generalForm.value.proxy.password = ''
    } else if (!generalForm.value.proxy.auth) {
        generalForm.value.proxy.username = ''
        generalForm.value.proxy.password = ''
    }

    // store new connection
    const { success, msg } = await connectionStore.saveConnection(
        isEditMode.value ? editName.value : null,
        generalForm.value,
    )
    if (!success) {
        $message.error(msg)
        return
    }

    $message.success(i18n.t('dialogue.handle_succ'))
    onClose()
}

const resetForm = () => {
    generalForm.value = connectionStore.newDefaultConnection()
    generalFormRef.value?.restoreValidation()
    testing.value = false
    testResult.value = null
    tab.value = 'general'
    loadingSentinelMaster.value = false
}

watch(
    () => dialogStore.connDialogVisible,
    (visible) => {
        if (visible) {
            resetForm()
            editName.value = get(dialogStore.connParam, 'name', '')
            generalForm.value = dialogStore.connParam || connectionStore.newDefaultConnection()
            dbFilterList.value = map(generalForm.value.dbFilterList, (item) => item + '')
            generalForm.value.ssh.loginType = generalForm.value.ssh.loginType || 'pwd'
            // update alias display
            const alias = get(generalForm.value, 'alias', {})
            const pairs = []
            for (const db in alias) {
                pairs.push({ db: parseInt(db), alias: alias[db] })
            }
            aliasPair.value = pairs
            generalForm.value.proxy.auth = !isEmpty(generalForm.value.proxy.username)
        }
    },
)

const onTestConnection = async () => {
    testResult.value = ''
    testing.value = true
    let result = ''
    try {
        const { success = false, msg } = await TestConnection(generalForm.value)
        if (!success) {
            result = msg
        }
    } catch (e) {
        result = e.message
    } finally {
        testing.value = false
    }

    if (!isEmpty(result)) {
        testResult.value = result
    } else {
        testResult.value = ''
    }
}

const onClose = () => {
    dialogStore.closeConnDialog()
}

const pasteFromClipboard = async () => {
    // url example:
    // rediss://user:password@localhost:6789/3?dial_timeout=3&db=1&read_timeout=6s&max_retries=2
    let opt = {}
    try {
        opt = await connectionStore.parseUrlFromClipboard()
    } catch (e) {
        $message.error(i18n.t('dialogue.connection.parse_fail', { reason: e.message }))
        return
    }
    generalForm.value.network = opt.network || 'tcp'
    generalForm.value.name = generalForm.value.addr = opt.addr
    generalForm.value.port = opt.port
    generalForm.value.username = opt.username
    generalForm.value.password = opt.password
    if (opt.connTimeout > 0) {
        generalForm.value.connTimeout = opt.connTimeout
    }
    if (opt.execTimeout > 0) {
        generalForm.value.execTimeout = opt.execTimeout
    }
    const { sslServerName = null } = opt
    if (sslServerName != null) {
        generalForm.value.ssl.enable = true
        if (!isEmpty(sslServerName)) {
            generalForm.value.ssl.sni = sslServerName
        }
    }
    $message.success(i18n.t('dialogue.connection.parse_pass', { url: opt.url }))
}
</script>

<template>
    <n-modal
        v-model:show="dialogStore.connDialogVisible"
        :closable="false"
        :mask-closable="false"
        :on-after-leave="resetForm"
        :show-icon="false"
        :title="isEditMode ? $t('dialogue.connection.edit_title') : $t('dialogue.connection.new_title')"
        close-on-esc
        preset="dialog"
        style="width: 600px"
        transform-origin="center"
        @esc="onClose">
        <n-spin :show="closingConnection">
            <n-tabs
                v-model:value="tab"
                animated
                pane-style="min-height: 50vh;"
                placement="left"
                tab-style="justify-content: right; font-weight: 420;"
                type="line">
                <!-- General pane -->
                <n-tab-pane :tab="$t('dialogue.connection.general')" display-directive="show:lazy" name="general">
                    <n-form
                        ref="generalFormRef"
                        :model="generalForm"
                        :rules="generalFormRules()"
                        :show-require-mark="false"
                        label-placement="top">
                        <n-grid :x-gap="10">
                            <n-form-item-gi
                                :label="$t('dialogue.connection.conn_name')"
                                :span="24"
                                path="name"
                                required>
                                <n-input
                                    v-model:value="generalForm.name"
                                    :placeholder="$t('dialogue.connection.name_tip')" />
                            </n-form-item-gi>
                            <n-form-item-gi
                                v-if="!isEditMode"
                                :label="$t('dialogue.connection.group')"
                                :span="24"
                                required>
                                <n-select
                                    v-model:value="generalForm.group"
                                    :options="groupOptions"
                                    :render-label="({ label, value }) => (value === '' ? $t(label) : label)" />
                            </n-form-item-gi>
                            <n-form-item-gi :label="$t('dialogue.connection.addr')" :span="24" path="addr" required>
                                <n-input-group>
                                    <n-select
                                        v-model:value="generalForm.network"
                                        :options="[
                                            { value: 'tcp', label: 'TCP' },
                                            { value: 'unix', label: 'UNIX' },
                                        ]"
                                        style="max-width: 100px" />
                                    <template v-if="generalForm.network === 'unix'">
                                        <n-input
                                            v-model:value="generalForm.sock"
                                            :placeholder="$t('dialogue.connection.sock_tip')" />
                                    </template>
                                    <template v-else>
                                        <n-input
                                            v-model:value="generalForm.addr"
                                            :placeholder="$t('dialogue.connection.addr_tip')" />
                                        <n-text style="width: 40px; text-align: center">:</n-text>
                                        <n-input-number
                                            v-model:value="generalForm.port"
                                            :max="65535"
                                            :min="1"
                                            :show-button="false"
                                            placeholder="6379"
                                            style="width: 200px" />
                                    </template>
                                </n-input-group>
                            </n-form-item-gi>
                            <n-form-item-gi :label="$t('dialogue.connection.pwd')" :span="12" path="password">
                                <n-input
                                    v-model:value="generalForm.password"
                                    :placeholder="$t('dialogue.connection.pwd_tip')"
                                    show-password-on="click"
                                    type="password" />
                            </n-form-item-gi>
                            <n-form-item-gi :label="$t('dialogue.connection.usr')" :span="12" path="username">
                                <n-input
                                    v-model:value="generalForm.username"
                                    :placeholder="$t('dialogue.connection.usr_tip')" />
                            </n-form-item-gi>
                        </n-grid>
                    </n-form>
                </n-tab-pane>

                <!-- Advance pane -->
                <n-tab-pane :tab="$t('dialogue.connection.advn.title')" display-directive="show" name="advanced">
                    <n-form
                        ref="advanceFormRef"
                        :model="generalForm"
                        :rules="generalFormRules()"
                        :show-require-mark="false"
                        label-placement="top">
                        <n-grid :x-gap="10">
                            <n-form-item-gi
                                :label="$t('dialogue.connection.advn.filter')"
                                :span="12"
                                path="defaultFilter">
                                <n-input
                                    v-model:value="generalForm.defaultFilter"
                                    :placeholder="$t('dialogue.connection.advn.filter_tip')" />
                            </n-form-item-gi>
                            <n-form-item-gi
                                :label="$t('dialogue.connection.advn.separator')"
                                :span="12"
                                path="keySeparator">
                                <n-input
                                    v-model:value="generalForm.keySeparator"
                                    :placeholder="$t('dialogue.connection.advn.separator_tip')" />
                            </n-form-item-gi>
                            <n-form-item-gi
                                :label="$t('dialogue.connection.advn.conn_timeout')"
                                :span="12"
                                path="connTimeout">
                                <n-input-number
                                    v-model:value="generalForm.connTimeout"
                                    :max="999999"
                                    :min="1"
                                    :show-button="false"
                                    style="width: 100%">
                                    <template #suffix>
                                        {{ $t('common.second') }}
                                    </template>
                                </n-input-number>
                            </n-form-item-gi>
                            <n-form-item-gi
                                :label="$t('dialogue.connection.advn.exec_timeout')"
                                :span="12"
                                path="execTimeout">
                                <n-input-number
                                    v-model:value="generalForm.execTimeout"
                                    :max="999999"
                                    :min="1"
                                    :show-button="false"
                                    style="width: 100%">
                                    <template #suffix>
                                        {{ $t('common.second') }}
                                    </template>
                                </n-input-number>
                            </n-form-item-gi>
                            <n-form-item-gi :label="$t('dialogue.connection.advn.key_view')" :span="12">
                                <n-radio-group v-model:value="generalForm.keyView">
                                    <n-radio-button
                                        :label="$t('dialogue.connection.advn.key_view_tree')"
                                        :value="KeyViewType.Tree" />
                                    <n-radio-button
                                        :label="$t('dialogue.connection.advn.key_view_list')"
                                        :value="KeyViewType.List" />
                                </n-radio-group>
                            </n-form-item-gi>
                            <n-form-item-gi :label="$t('dialogue.connection.advn.load_size')" :span="12">
                                <n-input-number
                                    v-model:value="generalForm.loadSize"
                                    :min="0"
                                    :show-button="false"
                                    style="width: 100%" />
                            </n-form-item-gi>
                            <n-form-item-gi :label="$t('dialogue.connection.advn.dbfilter_type')" :span="24">
                                <n-radio-group
                                    v-model:value="generalForm.dbFilterType"
                                    @update:value="onUpdateDBFilterType">
                                    <n-radio-button :label="$t('dialogue.connection.advn.dbfilter_all')" value="none" />
                                    <n-radio-button
                                        :label="$t('dialogue.connection.advn.dbfilter_show')"
                                        value="show" />
                                    <n-radio-button
                                        :label="$t('dialogue.connection.advn.dbfilter_hide')"
                                        value="hide" />
                                </n-radio-group>
                            </n-form-item-gi>
                            <n-form-item-gi
                                v-if="generalForm.dbFilterType !== 'none'"
                                :label="$t('dialogue.connection.advn.dbfilter_input')"
                                :span="24">
                                <n-select
                                    v-model:value="dbFilterList"
                                    :clearable="true"
                                    :disabled="generalForm.dbFilterType === 'none'"
                                    :placeholder="$t('dialogue.connection.advn.dbfilter_input_tip')"
                                    :show="false"
                                    :show-arrow="false"
                                    filterable
                                    multiple
                                    tag />
                            </n-form-item-gi>
                            <n-form-item-gi
                                :label="$t('dialogue.connection.advn.mark_color')"
                                :span="24"
                                path="markColor">
                                <div
                                    v-for="color in predefineColors"
                                    :key="color"
                                    :style="{
                                        backgroundColor: color,
                                        borderColor:
                                            generalForm.markColor === color
                                                ? themeVars.textColorBase
                                                : themeVars.borderColor,
                                    }"
                                    class="color-preset-item"
                                    @click="generalForm.markColor = color">
                                    <n-icon v-if="isEmpty(color)" :component="Close" size="24" />
                                </div>
                            </n-form-item-gi>
                        </n-grid>
                    </n-form>
                </n-tab-pane>

                <!-- Alias pane -->
                <n-tab-pane :tab="$t('dialogue.connection.alias.title')" display-directive="show:lazy" name="alias">
                    <n-form
                        :model="generalForm.alias"
                        :show-label="false"
                        :show-require-mark="false"
                        label-placement="top">
                        <n-form-item required>
                            <n-dynamic-input
                                v-model:value="aliasPair"
                                @create="onCreateAlias"
                                @update:value="onUpdateAlias">
                                <template #default="{ value }">
                                    <n-input-number
                                        v-model:value="value.db"
                                        :min="0"
                                        :placeholder="$t('dialogue.connection.alias.db')"
                                        :show-button="false"
                                        @update:value="onUpdateAlias" />
                                    <n-text>:</n-text>
                                    <n-input
                                        v-model:value="value.alias"
                                        :placeholder="$t('dialogue.connection.alias.value')"
                                        type="text"
                                        @update:value="onUpdateAlias" />
                                </template>
                                <template #action="{ index, create, remove, move }">
                                    <icon-button :icon="Delete" size="18" @click="() => remove(index)" />
                                    <icon-button :icon="Add" size="18" @click="() => create(index)" />
                                </template>
                            </n-dynamic-input>
                        </n-form-item>
                    </n-form>
                </n-tab-pane>

                <!-- SSL pane -->
                <n-tab-pane :tab="$t('dialogue.connection.ssl.title')" display-directive="show:lazy" name="ssl">
                    <n-form-item label-placement="left">
                        <n-checkbox v-model:checked="generalForm.ssl.enable" size="medium">
                            {{ $t('dialogue.connection.ssl.enable') }}
                        </n-checkbox>
                    </n-form-item>
                    <n-form
                        :disabled="!generalForm.ssl.enable"
                        :model="generalForm.ssl"
                        :show-require-mark="false"
                        label-placement="top">
                        <n-form-item :label="$t('dialogue.connection.ssl.cert_file')">
                            <file-open-input
                                v-model:value="generalForm.ssl.certFile"
                                :disabled="!generalForm.ssl.enable"
                                :placeholder="$t('dialogue.connection.ssl.cert_file_tip')" />
                        </n-form-item>
                        <n-form-item :label="$t('dialogue.connection.ssl.key_file')">
                            <file-open-input
                                v-model:value="generalForm.ssl.keyFile"
                                :disabled="!generalForm.ssl.enable"
                                :placeholder="$t('dialogue.connection.ssl.key_file_tip')" />
                        </n-form-item>
                        <n-form-item :label="$t('dialogue.connection.ssl.ca_file')" :show-feedback="false">
                            <file-open-input
                                v-model:value="generalForm.ssl.caFile"
                                :disabled="!generalForm.ssl.enable"
                                :placeholder="$t('dialogue.connection.ssl.ca_file_tip')" />
                        </n-form-item>
                        <n-form-item>
                            <n-checkbox v-model:checked="generalForm.ssl.allowInsecure" size="medium">
                                {{ $t('dialogue.connection.ssl.allow_insecure') }}
                            </n-checkbox>
                        </n-form-item>
                        <n-form-item :label="$t('dialogue.connection.ssl.sni')">
                            <n-input
                                v-model:value="generalForm.ssl.sni"
                                :placeholder="$t('dialogue.connection.ssl.sni')" />
                        </n-form-item>
                    </n-form>
                </n-tab-pane>

                <!-- SSH pane -->
                <n-tab-pane :tab="$t('dialogue.connection.ssh.title')" display-directive="show:lazy" name="ssh">
                    <n-form-item label-placement="left">
                        <n-checkbox v-model:checked="generalForm.ssh.enable" size="medium">
                            {{ $t('dialogue.connection.ssh.enable') }}
                        </n-checkbox>
                    </n-form-item>
                    <n-form
                        :disabled="!generalForm.ssh.enable"
                        :model="generalForm.ssh"
                        :show-require-mark="false"
                        label-placement="top">
                        <n-form-item :label="$t('dialogue.connection.addr')" required>
                            <n-input
                                v-model:value="generalForm.ssh.addr"
                                :placeholder="$t('dialogue.connection.ssh.addr_tip')" />
                            <n-text style="width: 40px; text-align: center">:</n-text>
                            <n-input-number
                                v-model:value="generalForm.ssh.port"
                                :max="65535"
                                :min="1"
                                :show-button="false"
                                style="width: 200px" />
                        </n-form-item>
                        <n-form-item :label="$t('dialogue.connection.ssh.login_type')">
                            <n-radio-group v-model:value="generalForm.ssh.loginType">
                                <n-radio-button :label="$t('dialogue.connection.pwd')" value="pwd" />
                                <n-radio-button :label="$t('dialogue.connection.ssh.pkfile')" value="pkfile" />
                            </n-radio-group>
                        </n-form-item>
                        <n-form-item
                            v-if="sshLoginType === 'pwd' || sshLoginType === 'pkfile'"
                            :label="$t('dialogue.connection.usr')">
                            <n-input
                                v-model:value="generalForm.ssh.username"
                                :placeholder="$t('dialogue.connection.ssh.usr_tip')" />
                        </n-form-item>
                        <n-form-item v-if="sshLoginType === 'pwd'" :label="$t('dialogue.connection.pwd')">
                            <n-input
                                v-model:value="generalForm.ssh.password"
                                :placeholder="$t('dialogue.connection.ssh.pwd_tip')"
                                show-password-on="click"
                                type="password" />
                        </n-form-item>
                        <n-form-item v-if="sshLoginType === 'pkfile'" :label="$t('dialogue.connection.ssh.pkfile')">
                            <file-open-input
                                v-model:value="generalForm.ssh.pkFile"
                                :disabled="!generalForm.ssh.enable"
                                :placeholder="$t('dialogue.connection.ssh.pkfile_tip')" />
                        </n-form-item>
                        <n-form-item v-if="sshLoginType === 'pkfile'" :label="$t('dialogue.connection.ssh.passphrase')">
                            <n-input
                                v-model:value="generalForm.ssh.passphrase"
                                :placeholder="$t('dialogue.connection.ssh.passphrase_tip')"
                                show-password-on="click"
                                type="password" />
                        </n-form-item>
                    </n-form>
                </n-tab-pane>

                <!-- Sentinel pane -->
                <n-tab-pane
                    :tab="$t('dialogue.connection.sentinel.title')"
                    display-directive="show:lazy"
                    name="sentinel">
                    <n-form-item label-placement="left">
                        <n-checkbox v-model:checked="generalForm.sentinel.enable" size="medium">
                            {{ $t('dialogue.connection.sentinel.enable') }}
                        </n-checkbox>
                    </n-form-item>
                    <n-form
                        :disabled="!generalForm.sentinel.enable"
                        :model="generalForm.sentinel"
                        :show-require-mark="false"
                        label-placement="top">
                        <n-form-item :label="$t('dialogue.connection.sentinel.master')">
                            <n-input-group>
                                <n-select
                                    v-model:value="generalForm.sentinel.master"
                                    :options="masterNameOptions"
                                    filterable
                                    tag />
                                <n-button
                                    :disabled="!generalForm.sentinel.enable"
                                    :loading="loadingSentinelMaster"
                                    @click="onLoadSentinelMasters">
                                    {{ $t('dialogue.connection.sentinel.auto_discover') }}
                                </n-button>
                            </n-input-group>
                        </n-form-item>
                        <n-form-item :label="$t('dialogue.connection.sentinel.password')">
                            <n-input
                                v-model:value="generalForm.sentinel.password"
                                :placeholder="$t('dialogue.connection.sentinel.pwd_tip')"
                                show-password-on="click"
                                type="password" />
                        </n-form-item>
                        <n-form-item :label="$t('dialogue.connection.sentinel.username')">
                            <n-input
                                v-model:value="generalForm.sentinel.username"
                                :placeholder="$t('dialogue.connection.sentinel.usr_tip')" />
                        </n-form-item>
                    </n-form>
                </n-tab-pane>

                <!-- Cluster pane -->
                <n-tab-pane :tab="$t('dialogue.connection.cluster.title')" display-directive="show:lazy" name="cluster">
                    <n-form-item label-placement="left">
                        <n-checkbox v-model:checked="generalForm.cluster.enable" size="medium">
                            {{ $t('dialogue.connection.cluster.enable') }}
                        </n-checkbox>
                    </n-form-item>
                    <!--                    <n-form-->
                    <!--                        :model="generalForm.cluster"-->
                    <!--                        :show-require-mark="false"-->
                    <!--                        :disabled="!generalForm.cluster.enable"-->
                    <!--                        label-placement="top">-->
                    <!--                    </n-form>-->
                </n-tab-pane>

                <!-- Proxy pane -->
                <n-tab-pane :tab="$t('dialogue.connection.proxy.title')" display-directive="show:lazy" name="proxy">
                    <n-radio-group v-model:value="generalForm.proxy.type" name="radiogroup">
                        <n-space size="large" vertical>
                            <n-radio :label="$t('dialogue.connection.proxy.type_none')" :value="0" />
                            <n-radio :label="$t('dialogue.connection.proxy.type_system')" :value="1" />
                            <n-radio :label="$t('dialogue.connection.proxy.type_custom')" :value="2" />
                            <n-form
                                :disabled="generalForm.proxy.type !== 2"
                                :model="generalForm.proxy"
                                :show-require-mark="false"
                                label-placement="top">
                                <n-grid :x-gap="10">
                                    <n-form-item-gi :show-label="false" :span="24" path="addr" required>
                                        <n-input-group>
                                            <n-select
                                                v-model:value="generalForm.proxy.schema"
                                                :consistent-menu-width="false"
                                                :options="[
                                                    { value: 'http', label: 'HTTP' },
                                                    { value: 'https', label: 'HTTPS' },
                                                    { value: 'socks5', label: 'SOCKS5' },
                                                    { value: 'socks5h', label: 'SOCKS5H' },
                                                ]"
                                                default-value="http"
                                                style="max-width: 100px" />
                                            <n-input
                                                v-model:value="generalForm.proxy.addr"
                                                :placeholder="$t('dialogue.connection.proxy.host')" />
                                            <n-text style="width: 40px; text-align: center">:</n-text>
                                            <n-input-number
                                                v-model:value="generalForm.proxy.port"
                                                :max="65535"
                                                :min="0"
                                                :show-button="false"
                                                style="width: 200px" />
                                        </n-input-group>
                                    </n-form-item-gi>
                                    <n-form-item-gi :show-label="false" :span="24" path="auth">
                                        <n-checkbox v-model:checked="generalForm.proxy.auth" size="medium">
                                            {{ $t('dialogue.connection.proxy.auth') }}
                                        </n-checkbox>
                                    </n-form-item-gi>
                                    <n-form-item-gi :label="$t('dialogue.connection.usr')" :span="12" path="username">
                                        <n-input
                                            v-model:value="generalForm.proxy.username"
                                            :disabled="!!!generalForm.proxy.auth"
                                            :placeholder="$t('dialogue.connection.proxy.usr_tip')" />
                                    </n-form-item-gi>
                                    <n-form-item-gi :label="$t('dialogue.connection.pwd')" :span="12" path="password">
                                        <n-input
                                            v-model:value="generalForm.proxy.password"
                                            :disabled="!!!generalForm.proxy.auth"
                                            :placeholder="$t('dialogue.connection.proxy.pwd_tip')"
                                            show-password-on="click"
                                            type="password" />
                                    </n-form-item-gi>
                                </n-grid>
                            </n-form>
                        </n-space>
                    </n-radio-group>
                </n-tab-pane>
            </n-tabs>

            <!-- test result alert-->
            <n-alert
                v-if="showTestResult"
                :on-close="() => (testResult = '')"
                :title="isEmpty(testResult) ? '' : $t('dialogue.connection.test_fail')"
                :type="isEmpty(testResult) ? 'success' : 'error'"
                closable>
                <template v-if="isEmpty(testResult)">{{ $t('dialogue.connection.test_succ') }}</template>
                <template v-else>{{ testResult }}</template>
            </n-alert>
        </n-spin>

        <template #action>
            <div class="flex-item-expand">
                <n-button :disabled="closingConnection" :focusable="false" :loading="testing" @click="onTestConnection">
                    {{ $t('dialogue.connection.test') }}
                </n-button>
            </div>
            <div class="flex-item n-dialog__action">
                <n-button :disabled="closingConnection" :focusable="false" @click="pasteFromClipboard">
                    {{ $t('dialogue.connection.parse_url_clipboard') }}
                </n-button>
                <n-button :disabled="closingConnection" :focusable="false" @click="onClose">
                    {{ $t('common.cancel') }}
                </n-button>
                <n-button :disabled="closingConnection" :focusable="false" type="primary" @click="onSaveConnection">
                    {{ isEditMode ? $t('preferences.general.update') : $t('common.confirm') }}
                </n-button>
            </div>
        </template>
    </n-modal>
</template>

<style lang="scss" scoped>
.color-preset-item {
    width: 24px;
    height: 24px;
    margin-right: 2px;
    border-width: 3px;
    border-style: solid;
    cursor: pointer;
    border-radius: 50%;
}
</style>
